#pragma

#include "log.hpp"
#include "string"
#include "Common.hpp"
#include <vector>
#include <unordered_map>
#include "DataManager.hpp"

using namespace LogModule;
using namespace DataManagerModule;

const std::string gsep = "\r\n";
const std::string glinesep = " ";
const std::string gHeaderLineSep = ": ";
const std::string ghttp_version = "HTTP/1.0";
const std::string gdefaulthomepage = "wwwroot";
const std::string gpage404 = "wwwroot/404.html";
const std::string gfirstpage = "index.html";
DataManager dm;

class HttpRequest
{
    // 请求行// GET /favicon.ico HTTP/1.1\r\n
    // 请求报头// Host: 8.137.19.140:8080
    //  Connection: keep-alive
    //  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0
    //  Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
    //  Referer: http://8.137.19.140:8080/?msg=i_have_sent_a_message_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_
    //  Accept-Encoding: gzip, deflate
    //  Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
    //  dnt: 1
    //  sec-gpc: 1
    // 空行//
    // 正文//

public:
    bool HasArgs()
    {
        return _isexec;
    }
    // 分析请求报头
    bool Parseheader(std::string &req_str)
    {
        std::string parstr;
        while (true)
        {
            bool b = ParseOneLine(req_str, parstr, gsep);
            if (b & !req_str.empty()) // 找到分隔符并且解析后字符串不为空
            {
                _req_header.push_back(parstr);
            }
            else if (b & req_str.empty()) // 读到空行
            {
                _blank_line = gsep;
                break;
            }
            else
                return false;
        }
        ParseHeaderkv();
        return true;
    }
    // 解析报头kv
    bool ParseHeaderkv()
    {
        std::string key, value;
        for (auto &str : _req_header)
        {
            if (SplitString(str, gHeaderLineSep, key, value))
            {
                _headerkv.insert(std::make_pair(key, value));
            }
        }
        return true;
    }
    // 请求反序列化
    void Deserialize(std::string &request_str)
    {
        // 分离请求行
        if (ParseOneLine(request_str, _req_line, gsep))
        {
            // 解析请求行
            ParseReqLine(_req_line);
            Parseheader(request_str);
            _body = request_str;
           
           //分析参数
           if(_method == "POST")
           {
                _isexec = true;
                _args = _body;
           }
           else if(_method == "GET")
           {
                auto pos = _uri.find("?");
                if(pos != std::string::npos)
                {
                    _isexec = true;
                    _path = _uri.substr(0,pos);
                    _args = _uri.substr(pos+1);
                }
           }

        }
    }
    // 获取请求内容
    std::string 
    
    Getcontent(const std::string &path)
    {
        std::string content;
        LOG(DEBUG)<<"请求文件名："<<path;
        if(std::filesystem::is_directory(path))
        {
            LOG(DEBUG)<<"非有效文件名";
            return "";
        }
        
        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
        {
            LOG(ERROR) << "file open error";
            return "";
        }
        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);
        content.resize(filesize);
        in.read(&content[0], filesize);
        in.close();
        LOG(DEBUG)<<"content length: "<<content.size();
        return content;
    }
    void Print()
    {
        LOG(INFO) << "_method: " << _method;
        LOG(INFO) << "_uri: " << _uri;
        LOG(INFO) << "_veision: " << _veision ;
        for (auto &kv : _headerkv)
        {
            LOG(INFO) << kv.first << ": " << kv.second;
        }
        LOG(INFO) << "_blank_line: " << _blank_line;
        LOG(INFO) << "_body: " << _body;
    }
    std::string Uri() { return _uri; }
    std::string SetUri(const std::string newuri)
    {
        _uri = newuri;
        return _uri;
    }
    std::string Body() {return _body;}
    std::string Method(){return _method;}
    std::string Path() { return _path; }
    std::string Args() { return _args; }
    std::string Suffix()
    {
        auto pos = _uri.rfind(".");
        if (pos == std::string::npos)
            return std::string(".html"); // 默认为html格式
        else
            return _uri.substr(pos);
    }

private:
    // 分析请求行
    void ParseReqLine(std::string &reqline)
    {
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _veision;
    }

    std::string _req_line;
    std::vector<std::string> _req_header; // 多行kv
    std::string _blank_line;              // 空行
    std::string _body;                    // 正文
    // 反序列化后解析数据
    std::string _method;
    std::string _uri;
    std::string _path;
    std::string _args;
    std::string _veision;
    std::unordered_map<std::string, std::string> _headerkv;
    bool _isexec = false; // 是否带参
};
class HttpResponse
{
public:
    HttpResponse()
        : _version(ghttp_version), _blank_line(gsep)
    {
    }
    // 构建应答
    void Build(HttpRequest &req)
    {
        std::string uri = gdefaulthomepage + req.Uri();
        if (uri.back() == '/')
        {
            uri += gfirstpage;
            req.SetUri(uri);
        }
        LOG(INFO) << "-------------client 请求uri: " << uri;
        req.Print();
        LOG(INFO) << "----------------------------------";
        _content = req.Getcontent(uri);
        if (_content.empty())
        {
            if(req.Method() != "POST")
            {
                // 请求的资源不存在
                LOG(DEBUG)<<"请求资源不存在";
                _status_code = 404;
                req.SetUri(gpage404);
                _content = req.Getcontent(gpage404);
            }
            else
            {
                // 成功接收POST正文信息
                LOG(DEBUG)<<"请求POST成功";
                _status_code = 200;
                _content = req.Body();
                dm.Write(_content);
            }
        }
        else
        {
            // 请求成功
            LOG(DEBUG)<<"请求资源成功";
            _status_code = 200;
        }
        _status_desc = Code2Desc(_status_code);
        if(!_content.empty())
        {
            Setheader("Content-Length",std::to_string(_content.size()));
        }
        std::string type = Suffix2Desc(req.Suffix());
        Setheader("Content-Type",type);
        //构建报头
        for(auto& pair:_head_kv)
        {
            _resp_header.push_back(pair.first + gHeaderLineSep + pair.second);
        }
    }
    //序列化
    void Serialize(std::string& resp_str)
    {
        _resp_line = _version + glinesep + std::to_string(_status_code) + glinesep + _status_desc + gsep;
        _body = _content;

        resp_str = _resp_line;
        for(auto& line:_resp_header)
        {
            resp_str += (line + gsep);
        }
        resp_str += _blank_line;
        resp_str += _body;
    }

private:
    std::string Suffix2Desc(const std::string &suffix)
    {
        if(suffix.empty())
            return "";
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".jpg")
            return "application/x-jpg";
        else if(suffix == ".ogg")
            return "audio/ogg";
        else if(suffix == ".wav")
            return "audio/wav";
        else if(suffix == "mp3")
            return "audio/mp3";
        else
            return "text/html";

    }

    void Setheader(const std::string& k,const std::string v)
    {
        _head_kv[k] = v;
    }

    std::string Code2Desc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
        case 404:
            return "Not Found";
        case 301:
            return "Move Permanently";
        case 302:
            return "Found";
        default:
            return "";
        }
    }

private:
    std::string _version;
    int _status_code;
    std::string _status_desc;
    std::string _content;
    std::unordered_map<std::string, std::string> _head_kv;
    // 应答部分
    std::string _resp_line;
    std::vector<std::string> _resp_header;
    std::string _blank_line;
    std::string _body;
};